package scene.shape.materials;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import raytracing.HitRecord;
import scene.lighting.Light;
import util.Color3f;
import util.MathUtil;
import util.Vector3f;

public class Texture extends Material {
	
	private BufferedImage image;
	private float scale = 1f;
	private float offsetu = 0f, offsetv = 0f;
	
	public Texture(Color3f color, String name) {
		super(color, name);
	}
	
	public Texture(String filename, String name){
		super(new Color3f(0,0,0), name);
		try {
			this.image = ImageIO.read(new File(filename));
		} catch (IOException e) {
			System.out.println(System.getProperty("user.dir"));
			System.out.println(filename);
			e.printStackTrace();
		}
	}
	
	public Texture(String filename, String name, float scale){
		super(new Color3f(0,0,0), name);
		this.scale = scale;
		try {
			this.image = ImageIO.read(new File(filename));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public Texture(String filename, String name, float scale, float offsetu, float offsetv){
		super(new Color3f(0,0,0), name);
		this.scale = scale;
		this.offsetu = offsetu;
		this.offsetv = offsetv;
		try {
			this.image = ImageIO.read(new File(filename));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public Color3f getUV(float uin, float vin){
		float u = uin % 1f, v = vin % 1f;
		float x = u * (image.getWidth()-1), y = v * (image.getHeight()-1);
		int rgb = image.getRGB((int)MathUtil.clamp(x, 0, image.getWidth()-1),(int)MathUtil.clamp(image.getHeight()-y, 0, image.getHeight()-1));
		float b = (rgb & 255) / 255f,
			  g = ((rgb >> 8) & 255) / 255f,
			  r = ((rgb >> 16) & 255) / 255f;
		return new Color3f(r,g,b);
	}
	
	public Color3f shade(HitRecord hr, Light light, int recursiondepth){
		Vector3f l = light.getPosition().subtract(hr.getIntersectionPoint()).normalize(),
				 n = hr.getNormal().normalize();
		float dot = Math.max(0,n.dot(l));//max(0,n.l)
		return getUV((hr.getPrimitive()).getU(hr)*scale + offsetu, hr.getPrimitive().getV(hr)*scale + offsetv).scale(dot);
	}
	
}
